using System;
using System.Collections;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.IO;
using System.Drawing;
using System.Text;
using System.Xml;
using System.Configuration;
using System.Windows.Forms;
using System.Reflection;
using Common.Utilities;
using Common.Utilities.DLR;
using Common.Utilities.Documents;
using Workflows.Components;
using Workflows.Components.DALC;
using Workflows.Components.Rules;
using Workflows.Designer.Export;
using Workflows.Designer.OfficeUtil;
using Workflows.Designer.Properties;
using Workflows.Diagrams;
using Divelements.Navisight;
using TD.SandDock;
using Rule=Workflows.Components.Rules.Rule;
using WindowsUserControl.Database;
using WindowsUserControl.Dialogs;
using System.Text.RegularExpressions;

namespace Workflows.Designer
{
    public partial class Main : Form, IMainForm
    {
        #region fields
        //private const int _timerDelay = 250;
        //private const Single _penDashRepeat = 7;
        // drag-drop
        Divelements.Navisight.NavigationBar toolItemNaviPanel;
        private Divelements.Navisight.NavigationBar ruleItemNaviPanel;
        private WorkflowComponentBase _SelectedToolboxItem;


        // workflow store 
        //private Dictionary<string,string> _DbConnectionCollection;
        // document 
        private Dictionary<Guid, TD.SandDock.TabbedDocument> _TabbedDocuments;
        //private WorkflowDesignControl2 _ActiveDoc;
        // edit
        private Northwoods.Go.GoCollection _clipBoard;
        // main form
        private bool _IsBusy;
        #endregion

        #region services
        private WorkflowService wfService;
        private JobDispatcherService jobService;
        #endregion

        #region init
        public Main()
        {
            InitializeComponent();
        }

        private void Main_Load(object sender, EventArgs e)
        {
            try
            {
                this._TabbedDocuments = new Dictionary<Guid, TD.SandDock.TabbedDocument>();
                // this.LoadInstallationSettings();
                this.PopulateDbStores();
                this.PopulateWorkflows();
                this.InitStepComponents();
                this.PopulateRules();
                this._clipBoard = new Northwoods.Go.GoCollection();
                //this._DbConnectionCollection = new Dictionary<string, string>();
                

                this.LoadFirstDesignDocument();
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        //private void LoadInstallationSettings()
        //{
        //    string backupFilePath = System.Reflection.Assembly.GetExecutingAssembly().Location + ".config.backup";
        //    if (System.IO.File.Exists(backupFilePath))
        //    {
        //        XmlDocument backupDoc = new XmlDocument();
        //        backupDoc.Load(backupFilePath);
        //        XmlNodeList addNodes = backupDoc.SelectNodes("appSettings/add");
        //        ConfigUtil configUtil = new ConfigUtil();
        //        if (addNodes != null && addNodes.Count > 0)
        //        {
        //            foreach (XmlNode addNode in addNodes)
        //            {
        //                string key = addNode.Attributes.GetNamedItem("key").Value;
        //                string val = addNode.Attributes.GetNamedItem("value").Value;
        //                configUtil.SetValue(key, val);
        //                System.Configuration.ConfigurationManager.AppSettings.Set(key, val);
        //            }
        //        }
        //        System.IO.File.Delete(backupFilePath);
        //    }

        //}

        private void PopulateDbStores()
        {
            this.cbo_WorkflowStores.Items.Clear();
            foreach(ConnectionStringSettings settings in ConfigurationManager.ConnectionStrings)
            {
                this.cbo_WorkflowStores.Items.Add(settings.Name);
            }
        }
        #endregion

        #region toolbox
        private void InitStepComponents()
        {
            this.p_ToolBox.Controls.Clear();
            this.toolItemNaviPanel = new Divelements.Navisight.NavigationBar();
            this.p_ToolBox.Controls.Add(this.toolItemNaviPanel);
            this.toolItemNaviPanel.Dock = DockStyle.Fill;

            string binFolderPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            DirectoryInfo dirInfo = new DirectoryInfo(binFolderPath);
            FileInfo[] dllFileInfos = dirInfo.GetFiles("*.dll");
            Dictionary<string, List<ToolItemBase>> toolItemsByCategory = new Dictionary<string, List<ToolItemBase>>();
            // int totalActivities = 0;
            if (dllFileInfos != null && dllFileInfos.Length > 0)
            {
                foreach (FileInfo dllInfo in dllFileInfos)
                {
                    bool include = false;
                    if(dllInfo.Name.ToLower().StartsWith("workflows.components") || 
                        dllInfo.Name.ToLower().StartsWith("discoverylogic") || 
                        dllInfo.Name.ToLower().StartsWith("dl.workflows.components"))
                    {
                        include = true;
                    }
                    if (include)
                    {
                        try
                        {
                            Assembly assembly = Assembly.LoadFile(dllInfo.FullName);
                            Type[] types = assembly.GetTypes();
                            foreach (Type type in types)
                            {
                                if (type.IsSubclassOf(typeof (WorkflowComponentBase)) && (!type.IsAbstract))
                                {
                                    WorkflowComponentBase wfComponent =
                                        Activator.CreateInstance(type) as WorkflowComponentBase;
                                    if (wfComponent != null)
                                    {
                                        ToolItemBase toolItem = new ToolItemBase();
                                        toolItem.Text = wfComponent.ComponentName;
                                        ImageList imgList = new ImageList();
                                        imgList.Images.Add(wfComponent.ComponentIcon);
                                        toolItem.ImageList = imgList;
                                        toolItem.ImageIndex = 0;
                                        toolItem.Description = wfComponent.Description;
                                        toolItem.WorkflowComponent =
                                            Activator.CreateInstance(type) as WorkflowComponentBase;
                                        toolItem.Category = wfComponent.ComponentCategory;
                                        if (toolItemsByCategory.ContainsKey(wfComponent.ComponentCategory))
                                        {
                                            List<ToolItemBase> toolItemList =
                                                toolItemsByCategory[wfComponent.ComponentCategory];
                                            toolItemList.Add(toolItem);
                                            toolItemsByCategory[wfComponent.ComponentCategory] = toolItemList;
                                        }
                                        else
                                        {
                                            List<ToolItemBase> toolItemList = new List<ToolItemBase>();
                                            toolItemList.Add(toolItem);
                                            toolItemsByCategory.Add(wfComponent.ComponentCategory, toolItemList);
                                        }

                                        // totalActivities++;
                                    }
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            ExceptionHandler.HandlesException(ex);
                            // MessageBox.Show("Unable to load assembly " + dllInfo.Name + ": " + ex.ToString());
                        }
                    }
                }

                // MessageBox.Show("Found " + totalActivities + " workflow activities");
                

                if (toolItemsByCategory.Count > 0)
                {
                    //string triggerCategoryName = "Triggers";
                    string [] categories = new string[toolItemsByCategory.Count];
                    toolItemsByCategory.Keys.CopyTo(categories, 0);
                    List<string> sortedCategoryNames = new List<string>();
                    sortedCategoryNames.AddRange(categories);
                    sortedCategoryNames.Sort();
                    //Hashtable htCategoryContainer = new Hashtable();
                    foreach(string category in sortedCategoryNames)
                    {
                        string categoryName = category.ToString();
                        Queue<char> queNameChar = new Queue<char>();
                        for (int k = 0; k < categoryName.Length; k++)
                        {
                            if (char.IsUpper(categoryName[k]) && k > 0 && categoryName[k] != ' ')
                            {
                                queNameChar.Enqueue(' ');
                                queNameChar.Enqueue(categoryName[k]);
                            }
                            else if (categoryName[k] == '_')
                            {
                                queNameChar.Enqueue(' ');
                            }
                            else
                            {
                                queNameChar.Enqueue(categoryName[k]);
                            }
                        }
                        char[] nameChars = new char[queNameChar.Count];
                        queNameChar.CopyTo(nameChars, 0);
                        categoryName = string.Empty;
                        for (int k = 0; k < nameChars.Length; k++)
                        {
                            categoryName += nameChars[k];
                        }

                        Divelements.Navisight.NavigationCategory naviCategory = new Divelements.Navisight.NavigationCategory();
                        naviCategory.Text = categoryName;
                        naviCategory.Image = global::Workflows.Designer.Properties.Resources.max;
                        this.toolItemNaviPanel.Controls.Add(naviCategory);
                        naviCategory.Dock = DockStyle.Fill;
                        Panel pToolContainer=new Panel();
                        pToolContainer.AutoScroll = true;
                        naviCategory.Controls.Add(pToolContainer);
                        pToolContainer.Dock = DockStyle.Fill;
                        List<ToolItemBase> toolItemList = toolItemsByCategory[category];
                        toolItemList.Sort();
                        for (int k = toolItemList.Count - 1; k >= 0; k--)
                        {
                            pToolContainer.Controls.Add(toolItemList[k]);
                            toolItemList[k].Dock = DockStyle.Top;
                            toolItemList[k].ToolItemSelectedEvent += new ToolItemSelected(Main_ToolItemSelectedEvent);
                        }

                        if (category == WorkflowComponentCategory.Triggers.ToString())
                        {
                            //triggerCategoryName = categoryName;
                        }
                    }
                    this.toolItemNaviPanel.SelectedCategoryChanged += new EventHandler(naviPanel_SelectedCategoryChanged);
                    this.naviPanel_SelectedCategoryChanged(this, new EventArgs());
                }

            }
        }

        void Main_ToolItemSelectedEvent(WorkflowComponentBase toolboxItem)
        {
            this._SelectedToolboxItem = toolboxItem;
            if (this.sandDockManager1.ActiveTabbedDocument != null)
            {
                try
                {
                    TD.SandDock.TabbedDocument tabbedDoc = this.sandDockManager1.ActiveTabbedDocument as TD.SandDock.TabbedDocument;
                    if (tabbedDoc != null)
                    {
                        WorkflowDesignControl2 designDoc = tabbedDoc.Controls[0] as WorkflowDesignControl2;
                        if (designDoc != null)
                        {
                            designDoc.DesignView.DoDragDrop(this._SelectedToolboxItem, DragDropEffects.All);
                        }
                    }

                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, ex.Source);
                }
            }
        }

        void naviPanel_SelectedCategoryChanged(object sender, EventArgs e)
        {
            if (this.toolItemNaviPanel.Controls.Count > 0)
            {
                for (int i = 0; i < this.toolItemNaviPanel.Controls.Count; i++)
                {
                    Divelements.Navisight.NavigationCategory naviCategory = this.toolItemNaviPanel.Controls[i] as Divelements.Navisight.NavigationCategory;
                    if (naviCategory != null)
                    {
                        naviCategory.Image = global::Workflows.Designer.Properties.Resources.max;
                    }
                }
            }
            if (this.toolItemNaviPanel.SelectedCategory != null)
            {
                this.toolItemNaviPanel.SelectedCategory.Image = global::Workflows.Designer.Properties.Resources.min;
            }
        }
        #endregion

        #region workflows
        private void refreshToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.PopulateWorkflows();
        }

        private void PopulateWorkflows()
        {
            WorkflowEngine engine = new WorkflowEngine();
            this.tree_Workflows.Nodes.Clear();
            List<WorkflowDesign> wfDesigns = WorkflowDesignDALC.GetAllWorkflowDesigns();
            if(wfDesigns !=null && wfDesigns.Count>0)
            {
                foreach(WorkflowDesign wfDesign in wfDesigns)
                {
                    TreeNode wfTn=new TreeNode(wfDesign.WorkflowName);
                    wfTn.ImageIndex = 1;
                    wfTn.SelectedImageIndex = 1;
                    WorkflowTriggerBase trigger = engine.GetWorkflowTrigger(wfDesign);
                    if(trigger !=null && trigger.IsActive)
                    {
                        wfTn.ImageIndex = 0;
                        wfTn.SelectedImageIndex = 0;
                    }
                    wfTn.Tag = wfDesign.WorkflowGuid;
                    this.tree_Workflows.Nodes.Add(wfTn);
                }
            }
            this.tree_Workflows.Refresh();
        }

        private void tree_Workflows_MouseUp(object sender, MouseEventArgs e)
        {
            this.tree_Workflows.SelectedNode = this.tree_Workflows.GetNodeAt(e.X, e.Y);
            if(this.tree_Workflows.SelectedNode !=null)
            {
                Guid wfID = (Guid) this.tree_Workflows.SelectedNode.Tag;
                if(e.Button==System.Windows.Forms.MouseButtons.Left)
                {
                    WorkflowDesign wfDesign = WorkflowDesignDALC.GetWorkflowDesign(wfID);
                    if (!string.IsNullOrEmpty(wfDesign.DesignDocumentFilePath) && File.Exists(wfDesign.DesignDocumentFilePath))
                    {
                        this.OpenWorkflowDesign(wfDesign.WorkflowName, wfDesign.DesignDocumentFilePath);
                    }
                    else
                    {
                        this.bar_Status.Text = "Retrieve workflow design binary files...";
                        this.Cursor = Cursors.WaitCursor;
                        byte[] woxFileContents = WorkflowDesignDALC.GetWoxFile(wfID);
                        if(woxFileContents !=null)
                        {
                            string appDataFolderPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
                            if (!Directory.Exists(appDataFolderPath))
                            {
                                Directory.CreateDirectory(appDataFolderPath);
                            }
                            string designFolderPath = System.IO.Path.Combine(appDataFolderPath, "workflow design");
                            System.IO.DirectoryInfo dirInfo = new System.IO.DirectoryInfo(designFolderPath);
                            if (!dirInfo.Exists)
                            {
                                dirInfo.Create();
                            }
                            string woxFilePath = Path.Combine(designFolderPath, wfDesign.WorkflowName + ".wox");
                            BinaryWriter bWriter=new BinaryWriter(File.OpenWrite(woxFilePath));
                            bWriter.Write(woxFileContents,0,woxFileContents.Length);
                            bWriter.Flush();
                            bWriter.Close();
                            wfDesign.DesignDocumentFilePath = woxFilePath;
                            this.OpenWorkflowDesign(wfDesign.WorkflowName, wfDesign.DesignDocumentFilePath);
                            
                        }
                        else
                        {
                            MessageBox.Show("The workflow design does not exist in local hard disk");
                        }

                        this.bar_Status.Text = string.Empty;
                        this.Cursor = Cursors.Default;
                    }
                }
            }
        }

        private void deleteWorkflowToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.btn_Delete_Click(this,new EventArgs());
        }
        #endregion

        #region rules
        private void ruleDesignerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            RuleDesigner ruleDesigner = new RuleDesigner();
            ruleDesigner.Show();
        }

        private void PopulateRules()
        {
            this.p_Rules.Controls.Clear();
            this.ruleItemNaviPanel = new NavigationBar();
            this.p_Rules.Controls.Add(this.ruleItemNaviPanel);
            this.ruleItemNaviPanel.Dock = DockStyle.Fill;

            ORMapping<Rule> orm=new ORMapping<Rule>();
            List<Rule> rules = orm.GetAll(ConfigurationManager.ConnectionStrings["Workflow"].ConnectionString);
            if (rules != null && rules.Count > 0)
            {
                Dictionary<string, List<Rule>> rulesByCategory = new Dictionary<string, List<Rule>>();
                foreach (Rule rule in rules)
                {
                    if(rulesByCategory.ContainsKey(rule.RuleCategory))
                    {
                        List<Rule> ruleList = rulesByCategory[rule.RuleCategory];
                        ruleList.Add(rule);
                        rulesByCategory[rule.RuleCategory] = ruleList;
                    }
                    else
                    {
                        List<Rule> ruleList=new List<Rule>();
                        ruleList.Add(rule);
                        rulesByCategory.Add(rule.RuleCategory,ruleList);
                    }
                }
            
                foreach (string categoryName in rulesByCategory.Keys)
                {
                    Queue<char> queNameChar = new Queue<char>();
                    for (int k = 0; k < categoryName.Length; k++)
                    {
                        if (char.IsUpper(categoryName[k]) && k > 0 && categoryName[k] != ' ')
                        {
                            queNameChar.Enqueue(' ');
                            queNameChar.Enqueue(categoryName[k]);
                        }
                        else if (categoryName[k] == '_')
                        {
                            queNameChar.Enqueue(' ');
                        }
                        else
                        {
                            queNameChar.Enqueue(categoryName[k]);
                        }
                    }
                    char[] nameChars = new char[queNameChar.Count];
                    queNameChar.CopyTo(nameChars, 0);
                    string strCategoryName = string.Empty;
                    for (int k = 0; k < nameChars.Length; k++)
                    {
                        strCategoryName += nameChars[k];
                    }

                    Divelements.Navisight.NavigationCategory naviCategory =
                        new Divelements.Navisight.NavigationCategory();
                    naviCategory.Text = strCategoryName;
                    naviCategory.Image = Resources.max;
                    this.ruleItemNaviPanel.Controls.Add(naviCategory);
                    naviCategory.Dock = DockStyle.Fill;

                    List<Rule> ruleList = rulesByCategory[categoryName];
                    for (int k = 0; k < ruleList.Count; k++)
                    {
                        ToolItemBase ruleToolItem = new ToolItemBase();
                        ruleToolItem.Text = ruleList[k].RuleName;
                        naviCategory.Controls.Add(ruleToolItem);
                        ruleToolItem.Dock = DockStyle.Top;
                        ruleToolItem.ToolItemSelectedEvent += new ToolItemSelected(Main_ToolItemSelectedEvent);
                    }
                }
                this.ruleItemNaviPanel.SelectedCategoryChanged +=
                    new EventHandler(ruleItemNaviPanel_SelectedCategoryChanged);
                this.ruleItemNaviPanel_SelectedCategoryChanged(this, new EventArgs());
            }
        }

        void ruleItemNaviPanel_SelectedCategoryChanged(object sender, EventArgs e)
        {
            if (this.ruleItemNaviPanel.Controls.Count > 0)
            {
                for (int i = 0; i < this.ruleItemNaviPanel.Controls.Count; i++)
                {
                    Divelements.Navisight.NavigationCategory naviCategory = this.ruleItemNaviPanel.Controls[i] as Divelements.Navisight.NavigationCategory;
                    if (naviCategory != null)
                    {
                        naviCategory.Image = Resources.max;
                    }
                }
            }
            if (this.toolItemNaviPanel.SelectedCategory != null)
            {
                this.toolItemNaviPanel.SelectedCategory.Image = Resources.min;
            }
        }
        #endregion

        #region Designer doc
        private void LoadFirstDesignDocument()
        {
            if (this.tabbedDocument1 != null)
            {
                try
                {
                    this.tabbedDocument1.Controls.Clear();
                    WorkflowDesignControl2 designDoc = new WorkflowDesignControl2();
                    this.tabbedDocument1.Controls.Add(designDoc);
                    designDoc.Dock = DockStyle.Fill;

                    designDoc.UpdatePropertyEvent += new Workflows.Diagrams.UpdateProperty(UpdateProperty);
                    designDoc.UpdateStatusEvent += new Workflows.Diagrams.UpdateStatus(this.UpdateStatus);
                    designDoc.UpdateTitleEvent += new Workflows.Diagrams.UpdateTitle(this.UpdateTitle);
                    this.tabbedDocument1.Text = designDoc.WorkflowName;
                    this.sandDockManager1.ActiveTabbedDocument = this.tabbedDocument1;
                    this.tabbedDocument1.Closing += new TD.SandDock.DockControlClosingEventHandler(TabbedDocumentClosing);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, ex.Source);
                }
            }
        }

        public void UpdateProperty(object obj)
        {
            this.propertyGrid1.SelectedObject = obj;
        }

        public void UpdateStatus(string message, int percent)
        {
            new WindowsUserControl.UIUpdateWrapper.StatusBarUpdator(this.statusStrip1, this.bar_Status,
                                                                                 message);
            new WindowsUserControl.UIUpdateWrapper.ProgressBarUpdator(this.statusStrip1, this.bar_Progress,
                                                                                   percent);
        }

        public void UpdateTitle(string title)
        {
            this.Text = string.Format("Workflow - {0}", title);
            if(this.sandDockManager1.ActiveTabbedDocument !=null)
            {
                this.sandDockManager1.ActiveTabbedDocument.Text = title;
            }
            //if(wfDesignCtr.Parent.GetType()==typeof(TabbedDocument))
            //{
            //    TabbedDocument activeTabbedDoc = wfDesignCtr.Parent as TabbedDocument;
            //    if(activeTabbedDoc !=null)
            //        activeTabbedDoc.Text = title;
            //}
        }

        public bool IsBusy
        {
            get { return _IsBusy; }
            set
            {
                _IsBusy = value;
                if (this._IsBusy)
                    this.Cursor = Cursors.WaitCursor;
                else
                    this.Cursor = Cursors.Default;
            }
        }

        public object DraggedObject
        {
            get { return _SelectedToolboxItem; }
            set { _SelectedToolboxItem = value as WorkflowComponentBase; }
        }
        #endregion

        #region menu
        #region new
        private void btn_New_Click(object sender, EventArgs e)
        {
            this.AddNewDesignDocument();
        }

        private void newToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.AddNewDesignDocument();
        }

        private TD.SandDock.TabbedDocument AddNewDesignDocument()
        {
            TD.SandDock.DocumentContainer docContainer = new TD.SandDock.DocumentContainer();
            this.Controls.Add(docContainer);
            WorkflowDesignControl2 designCtr = new WorkflowDesignControl2();
            designCtr.UpdatePropertyEvent += new UpdateProperty(this.UpdateProperty);
            designCtr.UpdateStatusEvent += new Workflows.Diagrams.UpdateStatus(this.UpdateStatus);
            designCtr.UpdateTitleEvent += new Workflows.Diagrams.UpdateTitle(this.UpdateTitle);

            TD.SandDock.TabbedDocument tabbedDoc = new TD.SandDock.TabbedDocument(this.sandDockManager1, docContainer, designCtr.WorkflowName);
            tabbedDoc.Open();
            tabbedDoc.Closing += new TD.SandDock.DockControlClosingEventHandler(TabbedDocumentClosing);
            tabbedDoc.Controls.Clear();
            tabbedDoc.Controls.Add(designCtr);
            designCtr.Dock = DockStyle.Fill;

            WorkflowDesign designDoc = (WorkflowDesign) designCtr.DesignView.Document.UserObject;
            this._TabbedDocuments.Add(designDoc.WorkflowGuid, tabbedDoc);
            return tabbedDoc;
        }
        #endregion

        #region open
        public void OpenWfDesign(string designFilePath)
        {
            TD.SandDock.TabbedDocument tabbedDoc = this.AddNewDesignDocument();
            Control child = tabbedDoc.Controls[0];
            if (child != null)
            {
                WorkflowDesignControl2 designCtr = child as WorkflowDesignControl2;
                if (designCtr != null)
                {
                    this.Open(tabbedDoc, designCtr, designFilePath);
                    
                }
            }
        }

        private void btn_Open_Click(object sender, EventArgs e)
        {
            TD.SandDock.TabbedDocument tabbedDoc = this.AddNewDesignDocument();
            Control child = tabbedDoc.Controls[0];
            if (child != null)
            {
                WorkflowDesignControl2 designCtr = child as WorkflowDesignControl2;
                if (designCtr != null)
                {
                    OpenFileDialog dlg = new OpenFileDialog();
                    dlg.Filter = "Workflow files(*.wox)|*.wox|All files(*.*)|*.*";
                    if (dlg.ShowDialog() == DialogResult.OK)
                    {
                        this.Open(tabbedDoc, designCtr, dlg.FileName);
                    }
                }
            }
        }

        private void OpenWorkflowDesign(string wfName, string filePath)
        {
            TD.SandDock.TabbedDocument tabbedDoc = this.AddNewDesignDocument();
            tabbedDoc.Text = wfName;
            Control child = tabbedDoc.Controls[0];
            if (child != null)
            {
                WorkflowDesignControl2 designCtr = child as WorkflowDesignControl2;
                if (designCtr != null)
                {
                    this.Open(tabbedDoc, designCtr, filePath);
                }
            }
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            TD.SandDock.TabbedDocument tabbedDoc = this.AddNewDesignDocument();
            Control child = tabbedDoc.Controls[0];
            if (child != null && child.GetType().IsSubclassOf(typeof(WorkflowComponentBase)))
            {
                WorkflowDesignControl2 designCtr = child as WorkflowDesignControl2;
                if (designCtr != null)
                {
                    OpenFileDialog dlg = new OpenFileDialog();
                    dlg.Filter = "Workflow files(*.wox)|*.wox|All files(*.*)|*.*";
                    if (dlg.ShowDialog() == DialogResult.OK)
                    {
                        this.Open(tabbedDoc, designCtr, dlg.FileName);
                    }
                }
            }
        }

        private void Open(TD.SandDock.TabbedDocument tabbedDoc, WorkflowDesignControl2 designCtr, string filePath)
        {
            designCtr.Open(filePath);
            WorkflowDesign wfDesign = designCtr.DesignView.Document.UserObject as WorkflowDesign;
            if (wfDesign != null)
            {
                tabbedDoc.Text = wfDesign.WorkflowName;
                this._TabbedDocuments.Remove(wfDesign.WorkflowGuid);
                if (this._TabbedDocuments.ContainsKey(wfDesign.WorkflowGuid))
                    this._TabbedDocuments[wfDesign.WorkflowGuid] = tabbedDoc;
                else
                    this._TabbedDocuments.Add(wfDesign.WorkflowGuid, tabbedDoc);
            }
            // WorkflowDesign designDoc = designCtr.DesignView.Document.UserObject as WorkflowDesignDocument;
        }
        #endregion

        #region close
        void TabbedDocumentClosing(object sender, TD.SandDock.DockControlClosingEventArgs e)
        {
            TabbedDocument tabbedDoc = (TabbedDocument) e.DockControl;
            WorkflowDesignControl2 designCtr = tabbedDoc.Controls[0] as WorkflowDesignControl2;

            if (designCtr != null)
            {
                WorkflowDesign wfDesign = designCtr.DesignView.Document.UserObject as WorkflowDesign;
                if (wfDesign != null)
                {
                    if (designCtr.IsDirty)
                    {
                        System.Windows.Forms.DialogResult dlgResult =
                            MessageBox.Show("The design has not saved, do you still want to close?",
                                            "Confirm closing", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning,
                                            MessageBoxDefaultButton.Button2);

                        if (dlgResult == System.Windows.Forms.DialogResult.Yes)
                            this._TabbedDocuments.Remove(wfDesign.WorkflowGuid);
                        else
                            e.Cancel = true;
                    }
                }
            }
        }

        #endregion

        #region save
        private void btn_Save_Click(object sender, EventArgs e)
        {
            if (this.sandDockManager1.ActiveTabbedDocument != null)
            {
                Control child = this.sandDockManager1.ActiveTabbedDocument.Controls[0];
                if (child != null)
                {
                    WorkflowDesignControl2 designCtr = child as WorkflowDesignControl2;
                    if (designCtr != null)
                        designCtr.Save();
                }
            }
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.sandDockManager1.ActiveTabbedDocument != null)
            {
                Control child = this.sandDockManager1.ActiveTabbedDocument.Controls[0];
                if (child != null)
                {
                    WorkflowDesignControl2 designCtr = child as WorkflowDesignControl2;
                    if (designCtr != null)
                        designCtr.Save();
                }
            }
        }

        private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.sandDockManager1.ActiveTabbedDocument != null)
            {
                Control child = this.sandDockManager1.ActiveTabbedDocument.Controls[0];
                if (child != null)
                {
                    WorkflowDesignControl2 designCtr = child as WorkflowDesignControl2;
                    SaveFileDialog dlg = new SaveFileDialog();
                    dlg.Filter = "Workflow files(*.wox)|*.wox|All files(*.*)|*.*";
                    if (dlg.ShowDialog() == DialogResult.OK)
                        this.SaveAs(designCtr, dlg.FileName);
                }
            }
        }

        private void Save(WorkflowDesignControl2 designCtr)
        {
            if (designCtr != null)
                designCtr.Save();
        }

        private void SaveAs(WorkflowDesignControl2 designCtr, string filePath)
        {
            if (designCtr != null)
                designCtr.SaveAs(filePath);
        }
        #endregion

        #region publish
        private void btn_Publish_Click(object sender, EventArgs e)
        {
            if (this.sandDockManager1.ActiveTabbedDocument != null)
            {
                WorkflowDesignControl2 designCtr = this.sandDockManager1.ActiveTabbedDocument.Controls[0] as WorkflowDesignControl2;
                try
                {
                    if (designCtr != null)
                    {
                        designCtr.Save();
                        WorkflowDesign wfDesign = designCtr.WorkflowDesign;
                        WorkflowTriggerInstanceDALC.ResetTriggerInstanceForWorkflow(wfDesign);
                        WorkflowDesignDALC.SaveWorkflowDesign(wfDesign);
                    }
                    this.PopulateWorkflows();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
            }
        }
        #endregion

        #region delete 
        private void btn_Delete_Click(object sender, EventArgs e)
        {
            if (this.tree_Workflows.SelectedNode != null)
            {
                Guid wfID = (Guid) this.tree_Workflows.SelectedNode.Tag;
                string wfName = this.tree_Workflows.SelectedNode.Text;
                DialogResult result =
                    MessageBox.Show("Are you sure to delete workflow [" + wfName + "]", "", MessageBoxButtons.YesNo);
                if (result == DialogResult.Yes)
                {
                    WorkflowDesignDALC.DeleteWorkflowDesign(wfID);
                    this.PopulateWorkflows();
                }
            }
        }
        #endregion

        #region print
        private void btn_Print_Click(object sender, EventArgs e)
        {
            this.Print();
        }

        private void printToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Print();
        }

        private void printPreviewToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Print();
        }

        private void Print()
        {
            if (this.sandDockManager1.ActiveTabbedDocument != null)
            {
                WorkflowDesignControl2 designCtr =
                    this.sandDockManager1.ActiveTabbedDocument.Controls[0] as WorkflowDesignControl2;
                if (designCtr != null)
                {
                    WorkflowDesign designDoc = designCtr.DesignView.Document.UserObject as WorkflowDesign;
                    if (designDoc != null)
                    {
                        try
                        {
                            Bitmap img = designCtr.DesignView.GetBitmapFromCollection(designCtr.DesignView.Document);
                            string tempFolderPath = FileUtil.GetWindowsAppFolderPath("Workflow") + "\\temp";
                            if (!System.IO.Directory.Exists(tempFolderPath))
                            {
                                System.IO.Directory.CreateDirectory(tempFolderPath);
                            }
                            string dateFolderName = DateTime.Now.Year.ToString() + "-" + DateTime.Now.Month.ToString() +
                                                    "-" +
                                                    DateTime.Now.Day.ToString();
                            string dateFolderPath = tempFolderPath + "\\" + dateFolderName;
                            if (!System.IO.Directory.Exists(dateFolderPath))
                            {
                                System.IO.Directory.CreateDirectory(dateFolderPath);
                            }
                            string tempFileName = FileUtil.FormatFileName(designDoc.WorkflowName) +
                                                  ".doc";
                            string tempFilePath = System.IO.Path.Combine(tempFolderPath, tempFileName);

                            System.Text.StringBuilder buffer = new StringBuilder();
                            // create header
                            buffer.Append("<html " +
                                          "xmlns:o='urn:schemas-microsoft-com:office:office' " +
                                          "xmlns:w='urn:schemas-microsoft-com:office:word'" +
                                          "xmlns='http://www.w3.org/TR/REC-html40'>" +
                                          "<head><title>" + designDoc.WorkflowName +
                                          "</title>");
                            buffer.Append("<!--[if gte mso 9]>" +
                                          "<xml>" +
                                          "<w:WordDocument>" +
                                          "<w:View>Print</w:View>" +
                                          "<w:Zoom>90</w:Zoom>" +
                                          "<w:DoNotOptimizeForBrowser/>" +
                                          "</w:WordDocument>" +
                                          "</xml>" +
                                          "<![endif]-->");
                            buffer.Append("<style>" +
                                          "<!-- /* Style Definitions */" +
                                          "@page Section1" +
                                          "   {size:8.5in 11.0in; " +
                                          "   margin:1.0in 1.25in 1.0in 1.25in ; " +
                                          "   mso-header-margin:.5in; " +
                                          "   mso-footer-margin:.5in; mso-paper-source:0;}" +
                                          " div.Section1" +
                                          "   {page:Section1;}" +
                                          "-->" +
                                          "</style></head>");

                            buffer.Append("<body lang=EN-US style='tab-interval:.5in'>" +
                                          "<div class=Section1>" +
                                          "<h1>" + designDoc.WorkflowName + "</h1>");
                            buffer.Append("<p style='color:red'><I>Create time:" +
                                          designDoc.CreationTime.ToString() + "</I></p>");
                            buffer.Append("<p style='color:blue'><b>Author: " +
                                          designDoc.Author + "</b></p>");
                            buffer.Append("</div></body></html>");

                            System.IO.StreamWriter writer = new StreamWriter(tempFilePath);
                            writer.Write(buffer.ToString());
                            writer.Flush();
                            writer.Close();

                            Microsoft.Office.Interop.Word.Application app =
                                new Microsoft.Office.Interop.Word.Application();
                            app.Visible = true;
                            object missingObj = Type.Missing;
                            object filePath = tempFilePath;
                            Microsoft.Office.Interop.Word.Document doc =
                                app.Documents.Open(ref filePath, ref missingObj,
                                                   ref missingObj, ref missingObj,
                                                   ref missingObj, ref missingObj,
                                                   ref missingObj, ref missingObj,
                                                   ref missingObj, ref missingObj,
                                                   ref missingObj, ref missingObj,
                                                   ref missingObj, ref missingObj,
                                                   ref missingObj, ref missingObj);

                            PictureWriter picWriter =
                                new PictureWriter(img, designDoc.WorkflowName,
                                                  designDoc.WorkflowName);
                            string picML = picWriter.ToString();

                            doc.Sections.Add(ref missingObj, ref missingObj).Range.InsertXML(picML, ref missingObj);
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.Message);
                        }
                    }
                }
            }
        }
        #endregion

        #region copy, cut paste
        private void btn_Cut_Click(object sender, EventArgs e)
        {
            if (this.sandDockManager1.ActiveTabbedDocument != null)
            {
                WorkflowDesignControl2 designCtr = this.sandDockManager1.ActiveTabbedDocument.Controls[0] as WorkflowDesignControl2;
                if (designCtr != null)
                    this._clipBoard = designCtr.Cut();
            }
        }

        private void btn_Copy_Click(object sender, EventArgs e)
        {
            if (this.sandDockManager1.ActiveTabbedDocument != null)
            {
                WorkflowDesignControl2 designCtr = this.sandDockManager1.ActiveTabbedDocument.Controls[0] as WorkflowDesignControl2;
                if (designCtr != null)
                    this._clipBoard = designCtr.Copy();
            }
        }

        private void btn_Paste_Click(object sender, EventArgs e)
        {
            if (this.sandDockManager1.ActiveTabbedDocument != null)
            {
                WorkflowDesignControl2 designCtr = this.sandDockManager1.ActiveTabbedDocument.Controls[0] as WorkflowDesignControl2;
                if (designCtr != null)
                    designCtr.Paste(this._clipBoard);
            }
        }

        private void cutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.sandDockManager1.ActiveTabbedDocument != null)
            {
                WorkflowDesignControl2 designCtr =
                    this.sandDockManager1.ActiveTabbedDocument.Controls[0] as WorkflowDesignControl2;
                if (designCtr != null)
                    this._clipBoard = designCtr.Cut();
            }
        }

        private void copyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.sandDockManager1.ActiveTabbedDocument != null)
            {
                WorkflowDesignControl2 designCtr = this.sandDockManager1.ActiveTabbedDocument.Controls[0] as WorkflowDesignControl2;
                if (designCtr != null)
                    this._clipBoard = designCtr.Copy();
            }
        }

        private void pasteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.sandDockManager1.ActiveTabbedDocument != null)
            {
                WorkflowDesignControl2 designCtr = this.sandDockManager1.ActiveTabbedDocument.Controls[0] as WorkflowDesignControl2;
                if (designCtr != null)
                    designCtr.Paste(this._clipBoard);
            }
        }
        #endregion

        #region undo/redo
        private void btn_Undo_Click(object sender, EventArgs e)
        {
            if (this.sandDockManager1.ActiveTabbedDocument != null)
            {
                WorkflowDesignControl2 designCtr = this.sandDockManager1.ActiveTabbedDocument.Controls[0] as WorkflowDesignControl2;
                if (designCtr != null)
                    designCtr.Undo();
            }
        }

        private void btn_Redo_Click(object sender, EventArgs e)
        {
        }

        private void undoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.sandDockManager1.ActiveTabbedDocument != null)
            {
                WorkflowDesignControl2 designCtr = this.sandDockManager1.ActiveTabbedDocument.Controls[0] as WorkflowDesignControl2;
                if (designCtr != null)
                    designCtr.Undo();
            }
        }

        private void redoToolStripMenuItem_Click(object sender, EventArgs e)
        {
        }
        #endregion

        #region group/ungroup
        private void btn_Group_Click(object sender, EventArgs e)
        {
            if (this.sandDockManager1.ActiveTabbedDocument != null)
            {
                WorkflowDesignControl2 designCtr = this.sandDockManager1.ActiveTabbedDocument.Controls[0] as WorkflowDesignControl2;
                if (designCtr != null)
                    designCtr.MakeSubGraph();
            }
        }

        private void btn_UnGroup_Click(object sender, EventArgs e)
        {
            if (this.sandDockManager1.ActiveTabbedDocument != null)
            {
                WorkflowDesignControl2 designCtr = this.sandDockManager1.ActiveTabbedDocument.Controls[0] as WorkflowDesignControl2;
                if (designCtr != null)
                    designCtr.RemoveSubGraph();
            }
        }
        #endregion

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }
        #endregion

        #region mainform

        #endregion

        //private void tabbedDocument1_Closing(object sender, TD.SandDock.DockControlClosingEventArgs e)
        //{
        //    TabbedDocument tabbedDoc =(TabbedDocument) e.DockControl;
        //    WorkflowDesignControl2 wfDesignCtr = tabbedDoc.Controls[0] as WorkflowDesignControl2;
        //    if(wfDesignCtr!=null)
        //    {
        //        if(wfDesignCtr.IsDirty)
        //        {
        //            System.Windows.Forms.DialogResult dlgResult =
        //                MessageBox.Show("The design is changed, do you still want to close it?", "Confirm close",
        //                                MessageBoxButtons.OKCancel);
        //            if(dlgResult==System.Windows.Forms.DialogResult.Cancel)
        //            {
        //                e.Cancel = true;
        //            }
        //        }
        //    }
        //}

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AboutBox1 aboutDlg=new AboutBox1();
            aboutDlg.Show(this);
        }

        private void propertyGrid1_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
        {
            if(this.propertyGrid1.SelectedObject.GetType()==typeof(WorkflowDesign) && this.sandDockManager1.ActiveTabbedDocument !=null)
            {
                WorkflowDesign wfDesign = (WorkflowDesign) this.propertyGrid1.SelectedObject;
                TabbedDocument tabDoc = (TabbedDocument) this.sandDockManager1.ActiveTabbedDocument;
                tabDoc.Text = wfDesign.WorkflowName;
            }
        }

        #region services
        private void startTestingToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.StartWorkflowService();
            this.StartJobDispatcherService();
        }

        private void stopTestingToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.StopWorkflowService();
            this.StopJobDispatcherService();
        }

        private void StartWorkflowService()
        {
            if (this.wfService != null)
            {
                if (!this.wfService.IsActive)
                {
                    this.wfService.Start();
                    this.desktopAlert1.ShowAlert("Workflow service started running...");
                }
            }
            else
            {
                this.wfService = new WorkflowService();
                this.wfService.Start();
                this.desktopAlert1.ShowAlert("Workflow service started running...");
            }
        }

        private void StopWorkflowService()
        {
            if(this.wfService !=null && this.wfService.IsActive)
            {
                this.wfService.Stop();
                this.desktopAlert1.ShowAlert("Workflow service stopped.");
            }
        }

        private void StartJobDispatcherService()
        {
            if(this.jobService !=null)
            {
                if(!this.jobService.IsActive)
                {
                    this.jobService.Start();
                    this.desktopAlert1.ShowAlert("Job dispatcher service started running...");
                }
            }
            else
            {
                this.jobService=new JobDispatcherService();
                this.jobService.Start();
                this.desktopAlert1.ShowAlert("Job dispatcher service started running...");
            }
        }

        private void StopJobDispatcherService()
        {
            if(this.jobService !=null)
            {
                if(this.jobService.IsActive)
                {
                    this.jobService.Stop();
                    this.desktopAlert1.ShowAlert("Job dispatcher service stopped.");
                }
            }
        }
        #endregion

        #region service controller
        private void serviceControllerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ServiceInstaller svcCtr=new ServiceInstaller();
            svcCtr.Show(this);
        }
        #endregion

        #region helps
        private void contentsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string helpFilePath = Path.Combine(Application.StartupPath, @"helps\bpm.chm");
            Help.ShowHelp(this,helpFilePath);
        }

        private void indexToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string helpFilePath = Path.Combine(Application.StartupPath, @"helps\bpm.chm");
            Help.ShowHelpIndex(this, helpFilePath);
        }

        private void searchToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string helpFilePath = Path.Combine(Application.StartupPath, @"helps\bpm.chm");
            Help.ShowHelp(this, helpFilePath, HelpNavigator.Find, "");
        }

        private void helpToolStripButton_Click(object sender, EventArgs e)
        {
            string helpFilePath = Path.Combine(Application.StartupPath, @"helps\bpm.chm");
            Help.ShowHelp(this, helpFilePath);
        }
        #endregion

        #region workflow store
        private void btn_AddConnection_Click(object sender, EventArgs e)
        {
            DatabaseBrowser dbBrowser = new DatabaseBrowser();
            dbBrowser.DatabaseSelectedEvent += new DatabaseBrowser.DatabaseSelected(dbBrowser_DatabaseSelectedEvent);
            dbBrowser.Show(this);
        }

        void dbBrowser_DatabaseSelectedEvent(string connStr)
        {
            ConfigUtil configUtil = new ConfigUtil();
            configUtil.ConfigType = ConfigUtil.ConfigFileType.AppConfig;
            Regex hostRegex = new Regex("server\\s*=\\s*([^\\S;])", RegexOptions.IgnoreCase);
            Match match = hostRegex.Match(connStr);
            string host = "localhost";
            if (match.Success)
            {
                host = match.Groups[1].Value;
            }
            else
            {
                hostRegex = new Regex("data\\s+source\\s*=\\s*([^\\S;])", RegexOptions.IgnoreCase);
                match = hostRegex.Match(connStr);
                if (match.Success)
                {
                    host = match.Groups[1].Value;
                }
            }
            
            configUtil.SetDbConnection(host, connStr);
            configUtil.SetDbConnection("Workflow", connStr);

            bool foundHost = false;
            if (this.cbo_WorkflowStores.Items.Count > 0)
            {
                for (int i = 0; i < cbo_WorkflowStores.Items.Count; i++)
                {
                    if (this.cbo_WorkflowStores.Items[i].ToString() == host)
                    {
                        this.cbo_WorkflowStores.SelectedIndex = i;
                        foundHost = true;
                        break;
                    }
                }
            }
            if (!foundHost)
            {
                this.cbo_WorkflowStores.Items.Add(host);
                this.cbo_WorkflowStores.SelectedIndex = this.cbo_WorkflowStores.Items.Count - 1;
            }
        }

        private void cbo_WorkflowStores_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (this.cbo_WorkflowStores.SelectedIndex >= 0)
            {
                string dbConnName = this.cbo_WorkflowStores.SelectedItem.ToString();
                string connStr = ConfigurationManager.ConnectionStrings[dbConnName].ConnectionString;
                ConfigUtil configUtil = new ConfigUtil();
                configUtil.ConfigType = ConfigUtil.ConfigFileType.AppConfig;
                configUtil.SetDbConnection("Workflow", connStr);
                this.PopulateWorkflows();
            }
        }
        #endregion 

        #region export
        private void exportAsConsoleAppToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.sandDockManager1.ActiveTabbedDocument != null)
            {
                Control child = this.sandDockManager1.ActiveTabbedDocument.Controls[0];
                if (child != null)
                {
                    WorkflowDesignControl2 designCtr = child as WorkflowDesignControl2;
                    WorkflowDesign wfDesign = designCtr.WorkflowDesign;
                    ExportAsConsoleApp exporter =new ExportAsConsoleApp(wfDesign);
                    exporter.Show(this);
                }
            }
        }

        private void sendToToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.sandDockManager1.ActiveTabbedDocument != null)
            {
                WorkflowDesignControl2 designCtr = this.sandDockManager1.ActiveTabbedDocument.Controls[0] as WorkflowDesignControl2;
                try
                {
                    if (designCtr != null)
                    {
                        WorkflowDesign wfDesign = designCtr.WorkflowDesign;
                        Bitmap workflowImg = designCtr.DesignView.GetBitmapFromCollection(designCtr.DesignView.Document);
                        EmailWorkflow emailWorkflow=new EmailWorkflow(wfDesign, workflowImg);
                        emailWorkflow.Show(this);
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
            }
        }
        #endregion

        private void clearHistoryToolStripMenuItem_Click(object sender, EventArgs e)
        {
            RunDALC.ClearRunHistory();
        }

        private void optionsToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }

        private void customizeToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }
    }
}